package com.ywz.project.system.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ywz.common.JWTUtils;
import com.ywz.common.ResultResp;
import com.ywz.common.StringUtils;
import com.ywz.common.TreeListUtils;
import com.ywz.project.base.system.entity.TSysMenu;
import com.ywz.project.base.system.entity.TSysPermission;
import com.ywz.project.base.system.entity.TSysRole;
import com.ywz.project.base.system.service.TSysMenuService;
import com.ywz.project.base.system.service.TSysPermissionService;
import com.ywz.project.base.system.service.TSysRoleService;
import com.ywz.project.system.dto.req.MenuPageReq;
import com.ywz.project.system.service.MenuApiService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class MenuApiServiceImpl implements MenuApiService {
    @Resource
    private TSysRoleService tSysRoleService;
    @Resource
    private TSysPermissionService tSysPermissionService;
    @Resource
    private TSysMenuService tSysMenuService;

    @Override
    public ResultResp getMenuPage(MenuPageReq req) {
        LambdaQueryWrapper<TSysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TSysMenu::getIsDeleted, 0);
        Page<TSysMenu> page = new Page<>(req.getPageNum(), req.getPageSize());
        return ResultResp.success(tSysMenuService.page(page, wrapper));
    }

    @Override
    public ResultResp getMenuTree() {
        List<TSysMenu> list = tSysMenuService.list();
        Integer i = list.stream().map(TSysMenu::getId).max(Comparator.comparing(Integer::intValue)).orElse(0);
        // 将菜单转成Tree结构
        List<TSysMenu> tSysMenus = TreeListUtils.listToTree(list, TSysMenu.class, "id", "parentId", 0, "children");
        tSysMenus.sort(Comparator.comparing(TSysMenu::getSort));
        tSysMenus.forEach(tSysMenu -> {
            tSysMenu.getChildren().sort(Comparator.comparing(TSysMenu::getSort));
        });
        Map<String, Object> map = new HashMap<>();
        map.put("topId", i);
        map.put("list", tSysMenus);
        return ResultResp.success(map);
    }

    @Override
    public ResultResp saveMenu(String req) {
        JSONObject jsonObject = JSONUtil.parseObj(req);
        // 获取集合列表
        JSONArray jsonArray = jsonObject.getJSONArray("list");
        // 保存的数据
        List<TSysMenu> list = new ArrayList<>();
        AtomicInteger sort = new AtomicInteger(1);
        jsonArray.forEach(json -> {
            TSysMenu menu = JSONUtil.toBean(json.toString(), TSysMenu.class);
            menu.setId(sort.get());
            menu.setSort(sort.get());
            menu.setParentId(0);
            // 二级菜单
            if (!TreeListUtils.isEmpty(menu.getChildren())) {
                List<TSysMenu> children = menu.getChildren();
                AtomicInteger childSort = new AtomicInteger(1);
                children.forEach(child -> {
                    child.setId(sort.get() * 100 + childSort.get());
                    child.setParentId(sort.get());
                    child.setSort(childSort.getAndIncrement());
                    child.setUpdatedTime(LocalDateTime.now());
                    list.add(child);
                });
            }
            menu.setUpdatedTime(LocalDateTime.now());
            list.add(menu);
            sort.getAndIncrement();
        });
        // 保存数据
        LambdaQueryWrapper<TSysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TSysMenu::getIsDeleted, 0);
        tSysMenuService.remove(wrapper);
        tSysMenuService.saveBatch(list);
        return ResultResp.success();
    }

    @Override
    public ResultResp getCurrentMenuTree() {
        // 获取当前登录用户
        String userId = JWTUtils.getCurrentTokenInfoByKey("userId");
        if (StringUtils.isEmpty(userId))
            return ResultResp.error("未获取到用户信息");
        // 根据用户id查询角色信息
        List<TSysRole> roleList = tSysRoleService.getRoleListByUserId(Integer.valueOf(userId));
        if (TreeListUtils.isEmpty(roleList))
            return ResultResp.error("未获取到角色信息");
        // 根据角色id集合查询权限
        List<Integer> roleIds = roleList.stream().map(TSysRole::getId).collect(Collectors.toList());
        List<TSysPermission> permissionList = tSysPermissionService.getPermissionListByRoleIds(roleIds);

        // 获取所有菜单
        List<TSysMenu> menuList = tSysMenuService.list();
        // 验证管理员角色
        AtomicBoolean adminFlag = new AtomicBoolean(false);
        roleList.forEach(role -> {
            if ("ROLE_ADMIN".equals(role.getRoleType())) {
                adminFlag.set(true);
            }
        });

        // 如果不是管理员则过滤菜单
        if (!adminFlag.get()) {
            List<String> menuNames = permissionList.stream().map(TSysPermission::getMenuNames).toList();
            // 获取当前用户拥有的菜单id
            Set<String> menuNameSet = new HashSet<>();
            menuNames.forEach(name -> {
                if (!StringUtils.isEmpty(name)){
                    String[] split = name.split(StringUtils.SEPARATOR);
                    menuNameSet.addAll(Arrays.asList(split));
                }
            });
            // 过滤菜单
            menuList = menuList.stream().filter(menu -> menuNameSet.contains(menu.getName())).collect(Collectors.toList());
        }
        // 获取最大id，用于前端生成id
        Integer maxId = menuList.stream().map(TSysMenu::getId).max(Comparator.comparing(Integer::intValue)).orElse(0);
        // 将菜单转成Tree结构
        List<TSysMenu> tSysMenus = TreeListUtils.listToTree(menuList, TSysMenu.class, "id", "parentId", 0, "children");
        tSysMenus.sort(Comparator.comparing(TSysMenu::getSort));
        tSysMenus.forEach(tSysMenu -> {
            tSysMenu.getChildren().sort(Comparator.comparing(TSysMenu::getSort));
        });

        Map<String, Object> map = new HashMap<>();
        map.put("topId", maxId);
        map.put("list", tSysMenus);
        return ResultResp.success(map);
    }
}
